#include "StdAfx.h"
#include <Windows.h>
#include <DbgHelp.h>
#include <Psapi.h>
#include "TraceSymbol.h"


TraceSymbol::TraceSymbol(void)
{
	m_symInit = false;
	m_process = NULL;
}


TraceSymbol::~TraceSymbol(void)
{
	if(m_symInit) {
		SymCleanup(m_process);
		m_symInit = FALSE;
	}
}

bool TraceSymbol::initSymbol(DWORD pid)
{
	SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
	m_process = OpenProcess(
		PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ,
		FALSE, pid);

	if(SymInitialize(m_process, NULL, TRUE)) {			
		m_symInit = true;
		return true;
	}
	return false;
}


// Get the symbol name ot the address
int TraceSymbol::GetSymbolNamefromAddress(DWORD_PTR address, CString & symbolInfo)
{
	DWORD64  dwDisplacement;
	char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME*sizeof(TCHAR)];
	memset(buffer, 0, sizeof(buffer));
	PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
	pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
	pSymbol->MaxNameLen = MAX_SYM_NAME;
	*(DWORD*)pSymbol->Name = MAX_SYM_NAME;
	if (m_symInit && SymFromAddr(m_process, address, &dwDisplacement, pSymbol))
	{
		IMAGEHLP_LINE64 line;
		TCHAR modeName[256];
		GetModuleFileNameEx(m_process, (HMODULE)pSymbol->ModBase,modeName, 255);
		line.SizeOfStruct = sizeof(line);
		DWORD displacement;
		if (SymGetLineFromAddr64(m_process, address, &displacement, &line)) {
			char *pFileName = strrchr(line.FileName, '\\');
			if(pFileName) {
				pFileName++;
			}
			else {
				pFileName = line.FileName;
			}
			symbolInfo.Format(_T( "%s      %s (%s:%d)"), modeName, (TCHAR*)CA2T(pSymbol->Name), (TCHAR*)CA2T(pFileName), line.LineNumber);
		}
		else {
			symbolInfo.Format(_T("%s      %s+0x%x"), modeName, (TCHAR*)CA2T(pSymbol->Name), dwDisplacement);
		}
	}
	else {
		symbolInfo.Format(_T("      No Symbol found for [%08x]"), address);
	}
	return 0;
}
